package com.br.pfm.persistence.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:pfm-sql.properties")
@ComponentScan("com.br.pfm")
public class JPAConfig {
	
	@Autowired
	Environment env;
	
	@Bean
	public Properties jpaProperties() {
		
		final Properties prop = new Properties();
		
		prop.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));
		prop.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
		prop.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
		prop.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
		prop.setProperty("hibernate.use_outer_join", env.getProperty("hibernate.use_outer_join"));
		prop.setProperty("hibernate.max_fetch_depth", env.getProperty("hibernate.max_fetch_depth"));
		prop.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
		prop.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
		prop.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
		prop.setProperty("hibernate.jdbc.batch_size", env.getProperty("hibernate.jdbc.batch_size"));
		prop.setProperty("hibernate.transaction.flush_before_completion", env.getProperty("hibernate.transaction.flush_before_completion"));
		prop.setProperty("hibernate.connection.release_mode", env.getProperty("hibernate.connection.release_mode"));
		prop.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
//		prop.setProperty("hibernate.use_sql_comments", env.getProperty("hibernate.use_sql_comments"));
		prop.setProperty("hibernate.c3p0.max_size", env.getProperty("hibernate.c3p0.max_size"));
		prop.setProperty("hibernate.c3p0.min_size", env.getProperty("hibernate.c3p0.min_size"));
		prop.setProperty("hibernate.c3p0.timeout", env.getProperty("hibernate.c3p0.timeout"));
		prop.setProperty("hibernate.c3p0.max_statements", env.getProperty("hibernate.c3p0.max_statements"));
		prop.setProperty("hibernate.c3p0.idle_test_period", env.getProperty("hibernate.c3p0.idle_test_period"));
		prop.setProperty("hibernate.c3p0.acquire_increment", env.getProperty("hibernate.c3p0.acquire_increment"));
		
		return prop;
	}
	
	/*
	@Bean
	public DataSource dataSource() {
		com.mchange.v2.c3p0.DriverManagerDataSource dataSource = new com.mchange.v2.c3p0.DriverManagerDataSource();
		
		dataSource.setDriverClass(env.getProperty("jdbc.driverClassName"));
		dataSource.setJdbcUrl(env.getProperty("jdbc.url"));
		dataSource.setUser(env.getProperty("jdbc.username"));
		dataSource.setPassword(env.getProperty("jdbc.password"));
		
		return dataSource;
	}
	*/
	
	@Bean
	public DataSource datasource() {
		EmbeddedDatabaseFactoryBean bean = new EmbeddedDatabaseFactoryBean();
		ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
		databasePopulator.addScript(new ClassPathResource("hibernate/config/java/schema.sql"));
		bean.setDatabasePopulator(databasePopulator);
		bean.afterPropertiesSet(); // necessary because
									// EmbeddedDatabaseFactoryBean is a
									// FactoryBean
		return bean.getObject();
	}
	
	@Bean
	public LocalSessionFactoryBean sessionFactory() {
		final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(datasource());
		sessionFactory.setPackagesToScan(new String[] { env.getProperty("hibernate.package_scan_classes") });
		sessionFactory.setHibernateProperties(jpaProperties());
		return sessionFactory;
	}
	
	@Bean
	public HibernateTransactionManager transactionManager() {
		final HibernateTransactionManager txManager = new HibernateTransactionManager();
		txManager.setSessionFactory(sessionFactory().getObject());
		return txManager;
	}
	
	@Bean
	public HibernateExceptionTranslator exceptionTranslation() {
		return new HibernateExceptionTranslator();
	}

}